<template>
  <div class="rbo-workflow-designer" :class="{ fullscreen: isFullscreen }">
    <div class="designer-header">
      <h3>RBO工作流设计器</h3>
      <div class="header-actions">
        <Button @click="toggleFullscreen" type="default">
          <IconifyIcon
            :icon="
              isFullscreen
                ? 'ant-design:fullscreen-exit-outlined'
                : 'ant-design:fullscreen-outlined'
            "
          />
          {{ isFullscreen ? '退出全屏' : '全屏' }}
        </Button>
        <Button @click="saveWorkflow" type="primary">
          <IconifyIcon icon="ant-design:save-outlined" />
          保存工作流
        </Button>
        <Button @click="exportWorkflow" type="default">
          <IconifyIcon icon="ant-design:export-outlined" />
          导出
        </Button>
      </div>
    </div>

    <div class="designer-content">
      <!-- 左侧工具栏 -->
      <div class="toolbar">
        <div class="toolbar-section">
          <h4>行为节点</h4>
          <div class="toolbar-items">
            <div
              v-for="node in behaviorNodes"
              :key="node.type"
              class="toolbar-item"
              draggable="true"
              @dragstart="onDragStart($event, node)"
            >
              <IconifyIcon :icon="node.icon" />
              <span>{{ node.label }}</span>
            </div>
          </div>
        </div>

        <div class="toolbar-section">
          <h4>控制节点</h4>
          <div class="toolbar-items">
            <div
              v-for="node in controlNodes"
              :key="node.type"
              class="toolbar-item"
              draggable="true"
              @dragstart="onDragStart($event, node)"
            >
              <IconifyIcon :icon="node.icon" />
              <span>{{ node.label }}</span>
            </div>
          </div>
        </div>

        <div class="toolbar-section">
          <h4>事件节点</h4>
          <div class="toolbar-items">
            <div
              v-for="node in eventNodes"
              :key="node.type"
              class="toolbar-item"
              draggable="true"
              @dragstart="onDragStart($event, node)"
            >
              <IconifyIcon :icon="node.icon" />
              <span>{{ node.label }}</span>
            </div>
          </div>
        </div>
      </div>

      <!-- 中间画布区域 -->
      <div class="canvas-container">
        <div
          class="workflow-canvas"
          @dragover="onDragOver"
          @drop="onDrop"
          @click="deselectAll"
          @mousemove="onMouseMove"
          @keydown.escape="cancelConnection"
        >
          <!-- 工作流节点 -->
          <div
            v-for="node in workflowNodes"
            :key="node.id"
            class="workflow-node"
            :class="{
              'node-selected': selectedNode?.id === node.id,
              [`node-type-${node.type}`]: true,
            }"
            :style="{
              left: node.x + 'px',
              top: node.y + 'px',
            }"
            @click.stop="selectNode(node)"
          >
            <div class="node-header">
              <IconifyIcon :icon="node.icon" />
              <span class="node-title">{{ node.label }}</span>
              <Button
                type="text"
                size="small"
                @click.stop="deleteNode(node.id)"
                class="delete-btn"
              >
                <IconifyIcon icon="ant-design:delete-outlined" />
              </Button>
            </div>
            <div class="node-content">
              <div v-if="node.type === 'behavior'" class="behavior-config">
                <div class="config-item">
                  <label>行为名称:</label>
                  <Input v-model="node.config.behaviorName" size="small" />
                </div>
                <div class="config-item">
                  <label>超时时间:</label>
                  <InputNumber v-model="node.config.timeout" size="small" />
                </div>
              </div>
              <div
                v-else-if="node.type === 'condition'"
                class="condition-config"
              >
                <div class="config-item">
                  <label>条件表达式:</label>
                  <Input v-model="node.config.expression" size="small" />
                </div>
              </div>
              <div v-else-if="node.type === 'event'" class="event-config">
                <div class="config-item">
                  <label>事件名称:</label>
                  <Input v-model="node.config.eventName" size="small" />
                </div>
              </div>
            </div>
            <!-- 连接点 -->
            <div class="connection-points">
              <div
                class="input-point"
                :class="{
                  connecting:
                    isConnecting && connectionStart?.point === 'output',
                }"
                @mousedown.stop="handleConnectionPointClick(node, 'input')"
              ></div>
              <div
                class="output-point"
                :class="{
                  connecting:
                    isConnecting && connectionStart?.point === 'input',
                }"
                @mousedown.stop="handleConnectionPointClick(node, 'output')"
              ></div>
            </div>
          </div>

          <!-- 连接线 -->
          <svg class="connections-svg">
            <defs>
              <marker
                id="arrowhead"
                markerWidth="10"
                markerHeight="7"
                refX="9"
                refY="3.5"
                orient="auto"
              >
                <polygon points="0 0, 10 3.5, 0 7" fill="#666" />
              </marker>
            </defs>
            <g>
              <path
                v-for="connection in connections"
                :key="connection.id"
                :d="getConnectionPath(connection)"
                stroke="#666"
                stroke-width="2"
                fill="none"
                marker-end="url(#arrowhead)"
                class="connection-line"
                @click="deleteConnection(connection.id)"
              />
              <!-- 正在绘制的连接线 -->
              <path
                v-if="isConnecting && connectionStart && mousePosition"
                :d="getTemporaryConnectionPath()"
                stroke="#1890ff"
                stroke-width="2"
                stroke-dasharray="5,5"
                fill="none"
                marker-end="url(#arrowhead)"
                class="temporary-connection"
              />
            </g>
          </svg>
        </div>
      </div>

      <!-- 右侧属性面板 -->
      <div class="properties-panel">
        <h4>属性配置</h4>
        <div v-if="selectedNode" class="node-properties">
          <Form layout="vertical" size="small">
            <FormItem label="节点ID">
              <Input v-model="selectedNode.id" disabled />
            </FormItem>
            <FormItem label="节点类型">
              <Input v-model="selectedNode.type" disabled />
            </FormItem>
            <FormItem label="节点标签">
              <Input v-model="selectedNode.label" />
            </FormItem>

            <!-- 根据节点类型显示不同的配置 -->
            <template v-if="selectedNode.type === 'behavior'">
              <FormItem label="行为名称">
                <Input v-model="selectedNode.config.behaviorName" />
              </FormItem>
              <FormItem label="超时时间(秒)">
                <InputNumber
                  v-model="selectedNode.config.timeout"
                  :min="1"
                  :max="3600"
                />
              </FormItem>
              <FormItem label="重试次数">
                <InputNumber
                  v-model="selectedNode.config.retry"
                  :min="0"
                  :max="10"
                />
              </FormItem>
            </template>

            <template v-else-if="selectedNode.type === 'condition'">
              <FormItem label="条件表达式">
                <Textarea v-model="selectedNode.config.expression" :rows="3" />
              </FormItem>
            </template>

            <template v-else-if="selectedNode.type === 'event'">
              <FormItem label="事件名称">
                <Input v-model="selectedNode.config.eventName" />
              </FormItem>
              <FormItem label="事件数据">
                <Textarea v-model="selectedNode.config.eventData" :rows="3" />
              </FormItem>
            </template>
          </Form>
        </div>
        <div v-else class="no-selection">
          <p>请选择一个节点来查看属性</p>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue';
import {
  Button,
  Input,
  InputNumber,
  Form,
  FormItem,
  Textarea,
  message,
} from 'ant-design-vue';
import { IconifyIcon } from '@vben/icons';

// 节点类型定义
interface WorkflowNode {
  id: string;
  type: string;
  label: string;
  icon: string;
  x: number;
  y: number;
  config: Record<string, any>;
}

interface Connection {
  id: string;
  from: string;
  to: string;
  fromPoint: 'output';
  toPoint: 'input';
}

// 工具栏节点定义
const behaviorNodes = [
  {
    type: 'behavior',
    label: '行为执行',
    icon: 'ant-design:play-circle-outlined',
  },
  { type: 'service', label: '服务调用', icon: 'ant-design:api-outlined' },
  { type: 'workflow', label: '子工作流', icon: 'ant-design:branches-outlined' },
];

const controlNodes = [
  {
    type: 'condition',
    label: '条件判断',
    icon: 'ant-design:question-circle-outlined',
  },
  { type: 'parallel', label: '并行执行', icon: 'ant-design:fork-outlined' },
  { type: 'loop', label: '循环执行', icon: 'ant-design:reload-outlined' },
];

const eventNodes = [
  {
    type: 'event',
    label: '事件发布',
    icon: 'ant-design:notification-outlined',
  },
  { type: 'listener', label: '事件监听', icon: 'ant-design:ear-outlined' },
];

// 响应式数据
const isFullscreen = ref(false);
const workflowNodes = ref<WorkflowNode[]>([]);
const connections = ref<Connection[]>([]);
const selectedNode = ref<WorkflowNode | null>(null);
const isConnecting = ref(false);
const connectionStart = ref<{ nodeId: string; point: string } | null>(null);
const mousePosition = ref<{ x: number; y: number } | null>(null);

// 全屏切换
const toggleFullscreen = () => {
  isFullscreen.value = !isFullscreen.value;
  if (isFullscreen.value) {
    document.body.style.overflow = 'hidden';
  } else {
    document.body.style.overflow = '';
  }
};

// 拖拽处理
const onDragStart = (event: DragEvent, node: any) => {
  if (event.dataTransfer) {
    event.dataTransfer.setData('application/json', JSON.stringify(node));
  }
};

const onDragOver = (event: DragEvent) => {
  event.preventDefault();
};

const onDrop = (event: DragEvent) => {
  event.preventDefault();
  const data = event.dataTransfer?.getData('application/json');
  if (data) {
    const nodeData = JSON.parse(data);
    const rect = (event.currentTarget as HTMLElement).getBoundingClientRect();
    const x = event.clientX - rect.left;
    const y = event.clientY - rect.top;

    addNode(nodeData, x, y);
  }
};

const onMouseMove = (event: MouseEvent) => {
  if (isConnecting.value) {
    const rect = (event.currentTarget as HTMLElement).getBoundingClientRect();
    mousePosition.value = {
      x: event.clientX - rect.left,
      y: event.clientY - rect.top,
    };
  }
};

// 节点操作
const addNode = (nodeData: any, x: number, y: number) => {
  const newNode: WorkflowNode = {
    id: `node_${Date.now()}`,
    type: nodeData.type,
    label: nodeData.label,
    icon: nodeData.icon,
    x,
    y,
    config: getDefaultConfig(nodeData.type),
  };

  workflowNodes.value.push(newNode);
  selectNode(newNode);
};

const getDefaultConfig = (type: string) => {
  switch (type) {
    case 'behavior':
      return { behaviorName: '', timeout: 60, retry: 1 };
    case 'condition':
      return { expression: '' };
    case 'event':
      return { eventName: '', eventData: '{}' };
    default:
      return {};
  }
};

const selectNode = (node: WorkflowNode) => {
  selectedNode.value = node;
};

const deselectAll = () => {
  selectedNode.value = null;
};

const deleteNode = (nodeId: string) => {
  workflowNodes.value = workflowNodes.value.filter(
    (node) => node.id !== nodeId,
  );
  connections.value = connections.value.filter(
    (conn) => conn.from !== nodeId && conn.to !== nodeId,
  );
  if (selectedNode.value?.id === nodeId) {
    selectedNode.value = null;
  }
};

// 连接操作
const startConnection = (node: WorkflowNode, point: string) => {
  console.log('开始连接:', node.id, point);
  isConnecting.value = true;
  connectionStart.value = { nodeId: node.id, point };
};

const completeConnection = (node: WorkflowNode, point: string) => {
  console.log(
    '完成连接:',
    node.id,
    point,
    '当前连接状态:',
    isConnecting.value,
    connectionStart.value,
  );

  if (!isConnecting.value || !connectionStart.value) {
    console.log('连接状态无效，直接开始新连接');
    startConnection(node, point);
    return;
  }

  // 检查是否是同一个节点
  if (connectionStart.value.nodeId === node.id) {
    console.log('不能连接同一个节点');
    cancelConnection();
    return;
  }

  // 检查连接点类型是否匹配
  if (connectionStart.value.point === point) {
    console.log('连接点类型不匹配');
    cancelConnection();
    return;
  }

  // 创建新连接
  const newConnection: Connection = {
    id: `conn_${Date.now()}`,
    from:
      connectionStart.value.point === 'output'
        ? connectionStart.value.nodeId
        : node.id,
    to:
      connectionStart.value.point === 'output'
        ? node.id
        : connectionStart.value.nodeId,
    fromPoint: 'output',
    toPoint: 'input',
  };

  console.log('创建新连接:', newConnection);

  // 检查是否已存在相同连接
  const existingConnection = connections.value.find(
    (conn) => conn.from === newConnection.from && conn.to === newConnection.to,
  );

  if (!existingConnection) {
    connections.value.push(newConnection);
    message.success('连接创建成功');
    console.log('连接创建成功，当前连接数:', connections.value.length);
  } else {
    message.warning('连接已存在');
    console.log('连接已存在');
  }

  cancelConnection();
};

const cancelConnection = () => {
  isConnecting.value = false;
  connectionStart.value = null;
  mousePosition.value = null;
};

const deleteConnection = (connectionId: string) => {
  connections.value = connections.value.filter(
    (conn) => conn.id !== connectionId,
  );
  message.success('连接删除成功');
};

const getTemporaryConnectionPath = () => {
  if (!connectionStart.value || !mousePosition.value) return '';

  const startNode = workflowNodes.value.find(
    (n) => n.id === connectionStart.value!.nodeId,
  );
  if (!startNode) return '';

  const startX =
    connectionStart.value.point === 'output' ? startNode.x + 150 : startNode.x;
  const startY = startNode.y + 25;
  const endX = mousePosition.value.x;
  const endY = mousePosition.value.y;

  const controlX1 = startX + 50;
  const controlY1 = startY;
  const controlX2 = endX - 50;
  const controlY2 = endY;

  return `M ${startX} ${startY} C ${controlX1} ${controlY1}, ${controlX2} ${controlY2}, ${endX} ${endY}`;
};

const getConnectionPath = (connection: Connection) => {
  const fromNode = workflowNodes.value.find((n) => n.id === connection.from);
  const toNode = workflowNodes.value.find((n) => n.id === connection.to);

  if (!fromNode || !toNode) return '';

  const fromX = fromNode.x + 150; // 节点宽度
  const fromY = fromNode.y + 25; // 节点高度的一半
  const toX = toNode.x;
  const toY = toNode.y + 25;

  const controlX1 = fromX + 50;
  const controlY1 = fromY;
  const controlX2 = toX - 50;
  const controlY2 = toY;

  return `M ${fromX} ${fromY} C ${controlX1} ${controlY1}, ${controlX2} ${controlY2}, ${toX} ${toY}`;
};

// 工作流操作
const saveWorkflow = () => {
  const workflow = {
    nodes: workflowNodes.value,
    connections: connections.value,
  };

  // 这里可以调用API保存工作流
  console.log('保存工作流:', workflow);
  message.success('工作流保存成功');
};

const exportWorkflow = () => {
  const workflow = {
    nodes: workflowNodes.value,
    connections: connections.value,
  };

  const dataStr = JSON.stringify(workflow, null, 2);
  const dataBlob = new Blob([dataStr], { type: 'application/json' });
  const url = URL.createObjectURL(dataBlob);

  const link = document.createElement('a');
  link.href = url;
  link.download = 'workflow.json';
  link.click();

  URL.revokeObjectURL(url);
  message.success('工作流导出成功');
};

// 暴露方法给父组件
defineExpose({
  getData: () => {
    return {
      nodes: workflowNodes.value,
      edges: connections.value,
      viewport: { x: 0, y: 0, zoom: 1 },
    };
  },
});
</script>

<style lang="less" scoped>
.rbo-workflow-designer {
  height: 100%;
  display: flex;
  flex-direction: column;
  transition: all 0.3s ease;

  &.fullscreen {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    z-index: 9999;
    background: #fff;
  }

  .designer-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 16px;
    border-bottom: 1px solid #f0f0f0;

    h3 {
      margin: 0;
    }

    .header-actions {
      display: flex;
      gap: 8px;
    }
  }

  .designer-content {
    flex: 1;
    display: flex;
    overflow: hidden;

    .toolbar {
      width: 250px;
      border-right: 1px solid #f0f0f0;
      padding: 16px;
      overflow-y: auto;

      .toolbar-section {
        margin-bottom: 24px;

        h4 {
          margin-bottom: 12px;
          color: #333;
        }

        .toolbar-items {
          .toolbar-item {
            display: flex;
            align-items: center;
            gap: 8px;
            padding: 8px 12px;
            border: 1px solid #d9d9d9;
            border-radius: 4px;
            margin-bottom: 8px;
            cursor: grab;
            background: #fff;
            transition: all 0.2s;

            &:hover {
              border-color: #1890ff;
              background: #f0f8ff;
            }

            &:active {
              cursor: grabbing;
            }
          }
        }
      }
    }

    .canvas-container {
      flex: 1;
      position: relative;
      overflow: hidden;

      .workflow-canvas {
        width: 100%;
        height: 100%;
        position: relative;
        background: #fafafa;
        cursor: default;

        .workflow-node {
          position: absolute;
          width: 150px;
          min-height: 60px;
          background: #fff;
          border: 2px solid #d9d9d9;
          border-radius: 6px;
          padding: 8px;
          cursor: move;
          user-select: none;

          &.node-selected {
            border-color: #1890ff;
            box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
          }

          &.node-type-behavior {
            border-color: #52c41a;
          }

          &.node-type-condition {
            border-color: #faad14;
          }

          &.node-type-event {
            border-color: #722ed1;
          }

          .node-header {
            display: flex;
            align-items: center;
            gap: 4px;
            margin-bottom: 8px;

            .node-title {
              flex: 1;
              font-weight: 500;
              font-size: 12px;
            }

            .delete-btn {
              opacity: 0;
              transition: opacity 0.2s;
            }
          }

          &:hover .delete-btn {
            opacity: 1;
          }

          .node-content {
            .config-item {
              margin-bottom: 4px;

              label {
                font-size: 10px;
                color: #666;
                display: block;
                margin-bottom: 2px;
              }
            }
          }

          .connection-points {
            position: absolute;
            top: 50%;
            transform: translateY(-50%);

            .input-point,
            .output-point {
              width: 12px;
              height: 12px;
              border-radius: 50%;
              background: #1890ff;
              cursor: crosshair;
              position: absolute;
              transition: all 0.2s;
              border: 2px solid #fff;
              box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);

              &:hover {
                background: #40a9ff;
                transform: scale(1.2);
              }

              &.connecting {
                background: #52c41a;
                animation: pulse 1s infinite;
              }
            }

            .input-point {
              left: -6px;
            }

            .output-point {
              right: -6px;
            }

            @keyframes pulse {
              0% {
                box-shadow: 0 0 0 0 rgba(82, 196, 26, 0.7);
              }
              70% {
                box-shadow: 0 0 0 10px rgba(82, 196, 26, 0);
              }
              100% {
                box-shadow: 0 0 0 0 rgba(82, 196, 26, 0);
              }
            }
          }
        }

        .connections-svg {
          position: absolute;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
          pointer-events: none;
          z-index: 1;

          .connection-line {
            pointer-events: stroke;
            cursor: pointer;
            transition: all 0.2s;

            &:hover {
              stroke-width: 3;
              stroke: #1890ff;
            }
          }

          .temporary-connection {
            pointer-events: none;
          }
        }
      }
    }

    .properties-panel {
      width: 300px;
      border-left: 1px solid #f0f0f0;
      padding: 16px;
      overflow-y: auto;

      h4 {
        margin-bottom: 16px;
        color: #333;
      }

      .node-properties {
        .ant-form-item {
          margin-bottom: 12px;
        }
      }

      .no-selection {
        text-align: center;
        color: #666;
        padding: 40px 20px;
      }
    }
  }
}
</style>
